<!-- components/Flexbox/FlexContainer.vue -->
<template>
  <div
      ref="containerRef"
      class="flex-container"
      :style="containerStyles"
      @slotchange="handleSlotChange"
  >
    <slot></slot>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'

const props = defineProps({
  display: {
    type: Boolean,
    default: true
  },
  flexDirection: {
    type: String,
    default: 'row',
    validator: (value) => [
      'row',
      'row-reverse',
      'column',
      'column-reverse'
    ].includes(value)
  },
  flexWrap: {
    type: String,
    default: 'nowrap',
    validator: (value) => ['nowrap', 'wrap', 'wrap-reverse'].includes(value)
  },
  flexFlow: String,
  justifyContent: {
    type: String,
    default: 'flex-start',
    validator: (value) => [
      'flex-start',
      'flex-end',
      'center',
      'space-between',
      'space-around',
      'space-evenly'
    ].includes(value)
  },
  alignItems: {
    type: String,
    default: 'stretch',
    validator: (value) => [
      'flex-start',
      'flex-end',
      'center',
      'baseline',
      'stretch'
    ].includes(value)
  },
  alignContent: {
    type: String,
    default: 'stretch',
    validator: (value) => [
      'flex-start',
      'flex-end',
      'center',
      'space-between',
      'space-around',
      'stretch'
    ].includes(value)
  },
  gap: {
    type: String,
    default: '0'
  },
  inline: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['resize', 'childAdded', 'childRemoved'])

const containerRef = ref(null)
let resizeObserver = null
let mutationObserver = null

const containerStyles = computed(() => {
  const styles = {
    gap: props.gap,
    justifyContent: props.justifyContent,
    alignItems: props.alignItems,
    alignContent: props.alignContent
  }

  if (props.display) {
    styles.display = props.inline ? 'inline-flex' : 'flex'
    styles.flexFlow = props.flexFlow
        ? props.flexFlow
        : `${props.flexDirection} ${props.flexWrap}`
  } else {
    styles.display = props.inline ? 'inline-block' : 'block'
  }

  return styles
})

const handleResize = (entries) => {
  for (const entry of entries) {
    const { width, height } = entry.contentRect
    emit('resize', { width, height })
  }
}

const handleMutation = (mutations) => {
  for (const mutation of mutations) {
    mutation.addedNodes.forEach(node => {
      if (node.nodeType === Node.ELEMENT_NODE) {
        emit('childAdded', node)
      }
    })
    mutation.removedNodes.forEach(node => {
      if (node.nodeType === Node.ELEMENT_NODE) {
        emit('childRemoved', node)
      }
    })
  }
}

onMounted(() => {
  // 初始化ResizeObserver
  resizeObserver = new ResizeObserver(handleResize)
  if (containerRef.value) {
    resizeObserver.observe(containerRef.value)
  }

  // 初始化MutationObserver
  mutationObserver = new MutationObserver(handleMutation)
  mutationObserver.observe(containerRef.value, {
    childList: true,
    subtree: false
  })
})

onUnmounted(() => {
  resizeObserver?.disconnect()
  mutationObserver?.disconnect()
})
</script>

<style scoped>
.flex-container {
  width: 100%;
  min-height: 50px;
  box-sizing: border-box;
}
</style>